﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using SSSGame.Physics;

namespace SSSGame.Physics
{
    public class VecteurVitesseLineaire
    {
        private Vector2 _Vecteur { get; set; }
        private float _BetaVecteur { get ; set; }
        private float _Norme { get; set; }

        public VecteurVitesseLineaire(Vector2 vecteur, float betavecteur, float norme)
        {
            _Vecteur = vecteur;
            _BetaVecteur = betavecteur;
            _Norme = norme;
        }

        public VecteurVitesseLineaire()
        {

        }

        public Vector2 DonnerVecteur()
        {
            return _Vecteur;
        }

        public float DonnerBetaVecteur()
        {
            return _BetaVecteur;
        }

        public void AffecterBetaVecteur(float valeur)
        {
            _BetaVecteur = valeur;
        }

        public float DonnerNorme()
        {
            return _Norme;
        }

        /// <summary>
        /// Retourne un vecteur vitesse complet (vecteur, norme, angle / abscisse)
        /// à partir des vecteurs vitesse et accélération liénaires
        /// </summary>
        /// <param name="NormeVecteurAcceleration"></param>
        /// <param name="DeltaTemps"></param>
        /// <param name="NormeVecteurVitesseInitiale"></param>
        /// <param name="BetaVecteurAcceleration"></param>
        /// <param name="BetaVecteurVitesseInitiale"></param>
        /// <returns></returns>
        public static VecteurVitesseLineaire DonnerNouveauVecteurVitesseLineaire(
            double NormeVecteurAcceleration,
            double DeltaTemps,
            double NormeVecteurVitesseInitiale,
            double BetaVecteurAcceleration,
            double BetaVecteurVitesseInitiale)
        {

            var Norme = (float)(Tools.ArrondirValeurNulle(Math.Sqrt(Math.Pow(NormeVecteurAcceleration, 2) * Math.Pow(DeltaTemps, 2) + Math.Pow(NormeVecteurVitesseInitiale, 2) +
                                           2 * (NormeVecteurAcceleration * DeltaTemps * NormeVecteurVitesseInitiale * Math.Cos(BetaVecteurAcceleration - BetaVecteurVitesseInitiale)))));

            // Calcul des composantes de l'accélération
            double Ax = Tools.ArrondirValeurNulle(NormeVecteurAcceleration * Math.Cos(BetaVecteurAcceleration));
            double Ay = Tools.ArrondirValeurNulle(NormeVecteurAcceleration * Math.Sin(BetaVecteurAcceleration));

            // Calcul des composantes de la vitesse initiale
            double V0x = Tools.ArrondirValeurNulle(NormeVecteurVitesseInitiale * Math.Cos(BetaVecteurVitesseInitiale));
            double V0y = Tools.ArrondirValeurNulle(NormeVecteurVitesseInitiale * Math.Sin(BetaVecteurVitesseInitiale));

            // Calcul des composantes de vitesse
            float Vx;
            float Vy;
            float betaVecteur = 0f;

            Vx = (float)Tools.ArrondirValeurNulle(Ax * DeltaTemps + V0x);
            Vy = (float)Tools.ArrondirValeurNulle(Ay * DeltaTemps + V0y);

            // Calcul de l'hypoténuse
            double vH = 0;

            if (Vx != 0 && Vy != 0)
            {
                vH = Math.Sqrt(Math.Pow(Vx, 2) + Math.Pow(Vy, 2));
                // Déduction de la valeur de l'angle :

                // Quart Nord-Est
                if (Vx > 0 && Vy < 0)
                    betaVecteur = (MathExtensions.PI * 2) - MathExtensions.Acos(Math.Abs(Vx / vH));
                // Quart Nord-Ouest
                if (Vx < 0 && Vy < 0)
                    betaVecteur = MathExtensions.Acos(Math.Abs(Vx / vH)) + MathExtensions.PI;
                // Quart Sud-Ouest
                else if (Vx < 0 && Vy > 0)
                    betaVecteur = (MathExtensions.PI) - MathExtensions.Acos(Math.Abs(Vx / vH));
                // Quart Sud-Est
                else if (Vx > 0 && Vy > 0)
                    betaVecteur = MathExtensions.Acos(Math.Abs(Vx / vH));
            }
            else
            {
                // Si Vx = 0, l'angle retourné est Pi/2 ou 3Pi/2, selon le signe de Vy
                if (Vx == 0)
                {
                    if (Vy > 0)
                    {
                        betaVecteur = (MathExtensions.PI / 2);
                    }
                    else if (Vy < 0)
                    {
                        betaVecteur = (3 * MathExtensions.PI / 2);
                    }
                    else
                        betaVecteur = (float)BetaVecteurVitesseInitiale;
                }
                else
                {
                    // Si Vy = 0, l'angle retourné est 0 ou Pi, selon le signe de Vx
                    if (Vy == 0)
                    {
                        if (Vx > 0)
                        {
                            betaVecteur = 0f;
                        }
                        else if (Vx < 0)
                        {
                            betaVecteur = (MathExtensions.PI);
                        }
                        else
                            betaVecteur = (float)BetaVecteurVitesseInitiale;
                    }
                }
            }

            return new VecteurVitesseLineaire(
                new Vector2(Vx, Vy),
                Tools.HarmoniserAngle(betaVecteur),
                Norme);
        }

        /// <summary>
        /// Donne le nouveau vecteur, calculé par pondération (contraintes d'affchage)
        /// </summary>
        /// <param name="positionInitiale"></param>
        /// <param name="coefficient"></param>
        /// <returns></returns>
        public Vector2 DonnerNouvellePosition(Vector2 positionInitiale, float coefficient)
        {
            return new Vector2(positionInitiale.X + _Vecteur.X / coefficient, positionInitiale.Y + _Vecteur.Y / coefficient);
        }
    }
}
